#include <iostream>
using namespace std;
//
//double Division(int a, int b)
//{
//	if (b == 0)
//	{
//		//throw "Divide by Zero Error";
//		//throw 7;
//		throw make_pair("Test", 7);
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func()
//{
//	try
//	{
//		cout << Division(3, 0) << endl;
//	}
//	catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	catch (int errid)
//	{
//		cout << "(Func中捕获)错误码: " << errid << endl;
//	}
//}
//
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch(const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	catch (int errid)
//	{
//		cout << "错误码: " << errid << endl;
//	}
//	catch (...)
//	{
//		cout << "unknown exception" << endl;
//	}
//
//	return 0;
//}





///////////////////////////////////////////////////////////自定义异常体系
#include<iostream>
#include <string>
#include <windows.h>
#include <time.h>
#include <memory>
using namespace std;

//double Division(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//		throw "Division by zero condition!";
//	else
//		return ((double)a / (double)b);
//}
//
//void Func()
//{
//	try
//	{
//		int len, time;
//		cin >> len >> time;
//		cout << Division(len, time) << endl;
//	}
//	catch (int errid)
//	{
//		cout << errid << endl;
//	}
//	/*catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}*/
//
//	cout << "Func() end" << endl;
//}
//
//int main()
//{
//	while (1)
//	{
//		try
//		{
//			Func();
//		}
//		catch (int errid)
//		{
//			cout << errid << endl;
//		}
//		catch (char errmsg)
//		{
//			cout << errmsg << endl;
//		}
//		/*catch (const char* errmsg)
//		{
//		cout << errmsg << endl;
//		}*/
//		catch (...) // 捕获任意类型的异常 -- 防止出现未捕获异常时，程序终止
//		{
//			cout << "未知异常" << endl;
//		}
//	}
//
//	return 0;
//}

//class Exception
//{
//public:
//	Exception(const string& errmsg, int id)
//		:_errmsg(errmsg)
//		, _errid(id)
//	{}
//
//	virtual string what() const
//	{
//		return _errmsg;
//	}
//
//	int GetErrid()
//	{
//		return _errid;
//	}
//
//protected:
//	string _errmsg;
//	int _errid;
//};

//double Division(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		Exception e("除0错误", 1);
//		throw e;
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func1()
//{
//	int len, time;
//	cin >> len >> time;
//	cout << Division(len, time) << endl;
//}
//
//void Func2()
//{
//
//}

// 1、抛异常可以抛任意类型对象
// 2、捕获时，要求类型匹配
//int main()
//{
//	while (1)
//	{
//		try
//		{
//			Func1();
//		}
//		catch (const Exception& e)
//		{
//			cout << e.what() << endl;
//		}
//		catch (...) // 捕获任意类型的异常 -- 防止出现未捕获异常时，程序终止
//		{
//			cout << "未知异常" << endl;
//		}
//	}
//
//	return 0;
//}

//#include <iostream>
//#include <string>
//#include <windows.h> // Sleep
//#include <time.h> // time
//using namespace std;
//// 服务器开发中通常使用的异常继承体系
//class Exception
//{
//public:
//	Exception(const string& errmsg, int id)
//		:_errmsg(errmsg)
//		, _id(id)
//	{}
//
//	virtual string what() const
//	{
//		return _errmsg;
//	}
//
//	int getid() const
//	{
//		return _id;
//	}
//
//protected:
//	string _errmsg;   // 错误信息
//	int _id;          // 错误码
//};
//
//class SqlException : public Exception // 数据库层
//{
//public:
//	SqlException(const string& errmsg, int id, const string& sql)
//		:Exception(errmsg, id)
//		, _sql(sql)
//	{}
//
//	virtual string what() const
//	{
//		string str = "SqlException:";
//		str += _errmsg;
//		str += "->";
//		str += _sql;
//
//		return str;
//	}
//protected:
//	const string _sql;
//};
//
//class CacheException : public Exception // 缓存层
//{
//public:
//	CacheException(const string& errmsg, int id)
//		:Exception(errmsg, id)
//	{}
//
//	virtual string what() const
//	{
//		string str = "CacheException:";
//		str += _errmsg;
//		return str;
//	}
//protected:
//	// stack<string> _stPath; // 加上堆栈信息可以查看上下文
//};
//
//class HttpServerException : public Exception // 网络层
//{
//public:
//	HttpServerException(const string& errmsg, int id, const string& type)
//		:Exception(errmsg, id)
//		, _type(type)
//	{}
//
//	virtual string what() const
//	{
//		string str = "HttpServerException:";
//		str += _type;
//		str += ":";
//		str += _errmsg;
//
//		return str;
//	}
//protected:
//	const string _type;
//};
//
//void SQLMgr() // 下面的缓存层没出问题就调数据库层
//{
//	srand(time(0));
//	if (rand() % 7 == 0)
//	{
//		throw SqlException("权限不足", 100, "select * from name = '张三'");
//	}
//
//	cout << "本次请求成功" << endl; // 最后调用的,前面都没出异常
//}
//void CacheMgr() // 下面的网络层没出问题就调缓存层
//{
//	srand(time(0));
//	if (rand() % 5 == 0)
//	{
//		throw CacheException("权限不足", 200);
//	}
//	else if (rand() % 6 == 0)
//	{
//		throw CacheException("数据不存在", 201);
//	}
//	SQLMgr();
//}
////void HttpServer() //网络层
////{
////	srand(time(0)); // 模拟
////	if (rand() % 3 == 0)
////	{
////		//throw HttpServerException("请求资源不存在", 100, "get");
////		throw HttpServerException("网络错误", 100, "get");
////	}
////	else if (rand() % 4 == 0)
////	{
////		throw HttpServerException("权限不足", 101, "post");
////	}
////	CacheMgr();
////}
//void SeedMsg(const string& s)
//{
//	// 要求出现网络错误重试三次
//	srand(time(0));
//	if (rand() % 3 == 0)
//	{
//		throw HttpServerException("网络错误", 100, "get");
//	}
//	else if (rand() % 4 == 0)
//	{
//		throw HttpServerException("权限不足", 101, "post");
//	}
//
//	cout << "发送成功: " << s << endl;
//}
//void HttpServer()
//{
//	// 要求出现网络错误，重试3次
//	string str = "等下吃什么";
//	int n = 3;
//	while (n--)
//	{
//		try
//		{
//			SeedMsg(str); // 重试3次
//			// 没有发生异常
//			break;
//		}
//		catch (const Exception& e)
//		{
//			if (e.getid() == 100 && n > 0)// 网络错误 且 重试3次内
//			{
//				continue;
//			}
//			else
//			{
//				throw e; // 重新抛出
//			}
//		}
//	}
//}
//
//int main()
//{
//	while (1)
//	{
//		Sleep(1000);
//		try
//		{
//			HttpServer(); // 先调用网络层
//		}
//		catch (const Exception& e) // 这里捕获父类对象就可以
//		{
//			// 多态
//			cout << e.what() << endl;
//			// 记录日志
//		}
//		catch (...) // 守住底线
//		{
//			cout << "unknown exception" << endl;
//		}
//	}
//	return 0;
//}

//#include <iostream>
//using namespace std;
//
//double Division(int a, int b)
//{
//	if (b == 0)
//	{
//		throw "Divide by Zero Error";
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func()
//{
//	int* array = new int[10];
//	int* array2 = nullptr;
//	try
//	{
//		array2 = new int[10];
//		try
//		{
//			cout << Division(3, 0) << endl;
//		}
//		catch (...)
//		{
//			cout << "delete []" << array << endl;
//			delete[] array;
//			cout << "delete2 []" << array2 << endl;
//			delete[] array2;
//			throw; // 捕获什么抛出什么
//		}
//	}
//	catch (...)
//	{
//		// 捕获new的异常
//	}
//	cout << "delete []" << array << endl;
//	delete[] array;
//	cout << "delete2 []" << array2 << endl;
//	delete[] array2;
//}
//
//int main()
//{
//
//	try
//	{
//		Func();
//	}
//	catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	catch (int errid)
//	{
//		cout << "错误码: " << errid << endl;
//	}
//	catch (...)
//	{
//		cout << "unknown exception" << endl;
//	}
//	cout << "return 0;" << endl;
//	return 0;
//}
//
//void MemoryLeaks()
//{
//	int* p1 = (int*)malloc(sizeof(int)); // 1.内存申请了忘记释放
//	int* p2 = new int;
//
//	int* p3 = new int[10]; // 2.异常安全问题
//
//	Func(); // 这里如果Func函数抛异常n，会导致 delete[] p3未执行，p3没被释放.
//	delete[] p3;
//}



double Division(int a, int b)
{
	if (b == 0)
	{
		throw "Divide by Zero Error";
	}
	else
	{
		return ((double)a / (double)b);
	}
}
// 1、利用RAII思想设计delete资源的类
// 2、重载operator*和opertaor->，具有像指针一样的行为。
// 3、浅拷贝问题（析构两次，下面讲）
template<class T>
class SmartPtr
{
public:
	SmartPtr(T* ptr)
		:_ptr(ptr)
	{}
	~SmartPtr()
	{
		cout << "delete: " << _ptr << endl;
		delete _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

	T* operator->()
	{
		return _ptr;
	}
protected:
	T* _ptr;
};

void Func()
{
	//1、如果p1这里new 抛异常会如何？
	//2、如果p2这里new 抛异常会如何？
	//3、如果div调用这里又会抛异常会如何？
	//int* p1 = new int;
	//int* p2 = new int;
	//cout << Division() << endl;
	//delete p1;
	//delete p2;
	//cout << "释放资源" << endl; 

	SmartPtr<int> sp1(new int);
	SmartPtr<int> sp2(new int);

	cout << Division(3, 0) << endl;
}
 
int main()
{
	try
	{
		Func();
	}
	catch (const char* errmsg)
	{
		cout << errmsg << endl;
	}
	catch (...)
	{
		cout << "unknown exception" << endl;
	}
	cout << "return 0;" << endl;
	return 0;
}
